# Entrenamiento con Adaline

import numpy as np # Para arreglos y computo cientifico, aqui para poder generar pesos aleatorios
import timeit # Para medir tiempo de ejecución

start = timeit.timeit() #Comenzamos a medir

ent = [[0,0,1], [0,1,0], [0,1,1], [1,0,0], [1,0,1],[1,1,0],[1,1,1]] #Definimos la información de entrenamiento, como muestra individual cada arreglo
esp = [1,2,3,4,5,6,7] #Definimos los valores esperados
lr = 0.3 # Definimos el valor del factor de aprendizaje
epochs = 10000 #Definimos el número de épocas

w1 = 0.84 # Declaramos pesos iniciales para reproducibilidas
w2 = 0.87 # Declaramos pesos iniciales para reproducibilidas
w3 = 0.78 # Declaramos pesos iniciales para reproducibilidas

#     w1 = np.random.randn(1) #por si queremos empezar con numeros aleatorios
#     w2 =  np.random.randn(1) #por si queremos empezar con numeros aleatorios
#     w3 =  np.random.randn(1) #por si queremos empezar con numeros aleatorios

for i in range(epochs): # Bucle sobre la epocas, número de veces que entrenamos con todos los ejemplos
    print('Epoca:', i) # imprimimos cada que inicia una poca
    cont = -1 # Contador para el valor leer esperado, empieza en menos uno ya que el indice en python empieza en cero
    for j in ent: #bucle sobre las entradas
        cont +=1 #incrementamos el contador
        neurona = w1 * j[0] + w2 * j[1] + w3 * j[2] # Hacemos el calculo normal de adaline
        error = esp[cont] - neurona #calculamos el error respecto al esperado correspondiente
        w1  = w1 + lr * j[0] * error # actualizamos peso 1
        w2  = w2 + lr * j[1] * error # actualizamos peso 2
        w3  = w3 + lr * j[2] * error # actualizamos peso 3
        print(w1, '\t', w2, '\t', w3) # Imprimimos el valor de los pesos actualizados
end = timeit.timeit() # Dejamos de contar el tiempo, aun que seria mejor comentar las impreisiones para medir
print(end - start) # Imprimimos tiempo de ejecucion

# Comprobación de los pesos obtenidos, validación

dato = [1,1,0]  # aqui podemos probar cualquier combinación de unos y ceros
neurona = w1 * dato[0] + w2 * dato[1] + w3 * dato[2] #calculamos la aproximación con adaline
neurona # Imprimimos el resultado